package com.yhb.channel.impl.MOCK;

import com.yhb.channel.PayChannel;
import com.yhb.channel.model.TryPayPayload;
import com.yhb.channel.dao.MOCK.MockChannelBoundRelationshipMapper;
import com.yhb.channel.dao.MOCK.MockChannelBoundRelationshipRecord;
import com.yhb.channel.exception.TryingBindCardException;
import com.yhb.channel.model.IBankCard;
import com.yhb.channel.provider.ChannelBaseService;
import com.yhb.channel.utils.ChannelJSONUtil;
import com.yhb.channel.utils.ChannelLogger;
import com.yhb.channel.utils.ChannelStringUtils;
import me.edzh.spring.bootstrap.service.SMSService;
import org.apache.http.util.TextUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class MockChannel implements PayChannel {
    /**
     * 常量
     */
    public static final String CHANNEL_NAME = "Mock通道";
    private static final String MOCK_REDIS_TRY_PAY_TOKEN_KEY_PREFIX = "mock-redis-try-pay-token-key-prefix-";
    private static ChannelLogger logger;
    private static final String MOCK_REDIS_BIND_CARD_SMS_PREFIX = "mock-redis-bind-card-sms-prefix-";
    private static final long ONE_DAY = 24 * 3600 * 1000; // 一天

    /* ------------Base Provider Beans or utils------------ */
    @Autowired
    private ChannelBaseService channelBaseService;

    @Autowired
    private MockChannelBoundRelationshipMapper dbMapper;

    @Autowired
    private SMSService smsService; // todo 删除

    @PostConstruct
    private void init() {
        logger = new ChannelLogger(CHANNEL_NAME, MockException.class, channelBaseService.iUtilProvider);
    }


    private void saveRequestFlow(String flow) {
        channelBaseService.iUtilProvider.savePayChannelFlow(CHANNEL_NAME + "---", flow);
    }

    private boolean checkIfRegistered(String userId) {
        String channelUserId = dbMapper.selectMockChannelUserIdByYHBUserId(userId);
        if (null == channelUserId) {
            logger.info(userId + "未签约过");
            return false;
        }
        logger.info(userId + "已经签约过，channelUserId：" + channelUserId);
        return true;
    }

    public boolean checkIfBound(@NotNull IBankCard card) {
        MockChannelBoundRelationshipRecord record = dbMapper.getRecordByCardId(card.getId());
        return null != record && record.getBound() == 1;
    }

    /**
     * 以下业务方法
     */

//    @Override
//    public void userSignUp(String userId, String province, String city, @NotNull IBankCard card, String payRate) {
//        String channelUserId = UUID.randomUUID().toString();
//        int bound = 1;
//        int isBillingCard = 1; // 标志结算卡
//        logger.info("准备落库结算卡 通道用户id：" + channelUserId);
//        MockChannelBoundRelationshipRecord record = MockChannelBoundRelationshipRecord.builder()
//                .cardId(card.getId())
//                .cardType(card.getCardType())
//                .isBillingCard(isBillingCard)
//                .bound(bound)
//                .channelUserId(channelUserId)
//                .agreementNo("")
//                .userId(userId)
//                .build();
//        dbMapper.insert(record);
//        logger.info("SignUpMock 成功");
//    }

    @Override
    public void updatePayRate(String userId, String payRate) {

    }

    @Override
    public String bindCard(String userId, @NotNull IBankCard card, String clientIP) {
        String phoneNumber = card.getPhoneNumber();
        HashMap<String, String> param = new HashMap<>();
        String code = (int) ((Math.random() * 9 + 1) * 100000) + "";
        param.put("code", code);
        smsService.sendSms(phoneNumber, "SMS_174025563", param);
        String smsUUID = UUID.randomUUID().toString();
        HashMap<String, String> val = new HashMap<String, String>() {
            {
                put("cardId", card.getId());
                put("code", code);
                put("cardType", Integer.toString(card.getCardType()));
            }
        };
        channelBaseService.redis.boundValueOps(MOCK_REDIS_BIND_CARD_SMS_PREFIX + smsUUID).set(ChannelJSONUtil.toJson(val),
                ONE_DAY, TimeUnit.MILLISECONDS);
        return smsUUID;
    }

    @Override
    public String bindCardConfirm(String smsCode, String userId, String smsUUID) {
        String valStr = channelBaseService.redis.boundValueOps(MOCK_REDIS_BIND_CARD_SMS_PREFIX + smsUUID).get();
        if (valStr == null || valStr.isEmpty()) {
            throw new MockSMSExpiredException(MockConstant.SMS_EXPIRED, "短信已过期!");
        }
        HashMap val = ChannelJSONUtil.parseJson(valStr, HashMap.class);
        int cardType = Integer.parseInt((String) val.get("cardType"));
        String code = (String) val.get("code");
        String cardId = (String) val.get("cardId");
        if (TextUtils.isEmpty(smsCode) || !smsCode.equals(code)) {
            logger.fail(-233333, "短信不匹配");
        }
        String agreementNo = UUID.randomUUID().toString();
        logger.info("开始交易卡落库 协议号:" + agreementNo);
        /*
          判断交易卡是不是和结算卡同一张 防止重复插入同个cardId
         */
        MockChannelBoundRelationshipRecord existRecord = dbMapper.getRecordByCardId(cardId);
        if (existRecord != null) {
            // 更新已有结算卡
            existRecord.setAgreementNo(agreementNo);
            existRecord.setBound(1);
            dbMapper.updateByCardId(existRecord);
        } else {
            // 插入消费卡
            int bounded = 1;
            String channelUserId = dbMapper.selectMockChannelUserIdByYHBUserId(userId);
            int isNotBillingCard = 0;
            MockChannelBoundRelationshipRecord record = MockChannelBoundRelationshipRecord.builder()
                    .cardId(cardId)
                    .userId(userId)
                    .cardType(cardType)
                    .agreementNo(agreementNo)
                    .bound(bounded)
                    .channelUserId(channelUserId)
                    .isBillingCard(isNotBillingCard)
                    .build();
            dbMapper.insert(record);
        }
        logger.info("bindCardConfirm 成功，cardId:" + cardId);
        return cardId;
    }

//    @Override
//    public String tryBindCard(String userId, @NotNull IBankCard card, String clientIP, String payRate) {
//        boolean registered = this.checkIfRegistered(userId); // 是否签约过
//        int cardType = card.getCardType(); // 0 - 储蓄卡, 1 - 信用卡
//        if (!registered) {
//            if (cardType == 1) {
//                logger.fail(MockConstant.NOT_SIGNED, "该用户未签约过，请先签约");
//                return ""; // @reachable
//            }
//            this.userSignUp(userId, card.getProvince(), card.getCity(), card, payRate);
//        }
//        return this.bindCard(userId, card, clientIP);
//    }
//
//    @Override
//    public String pay(String userId, IBankCard payCard, IBankCard remitCard,
//                      BigDecimal orderAmount, BigDecimal userFeeAmount, String clientIP) {
//        return UUID.randomUUID().toString();
//    }

//    @Override
//    public String tryPay(String userId, IBankCard payCard, IBankCard remitCard,
//                         BigDecimal orderAmount, BigDecimal userFeeAmount, String clientIP, String payRate)
//            throws TryingBindCardException {
//        if (!this.checkIfBound(payCard)) {
//             String bindCardUUID = this.bindCard(userId, payCard, clientIP);
//             TryPayPayload payload = TryPayPayload.builder()
//                     .payCard(payCard)
//                     .remitCard(remitCard)
//                     .bindCardUUID(bindCardUUID)
//                     .orderAmount(orderAmount)
//                     .userFeeAmount(userFeeAmount)
//                     .userId(userId)
//                     .build();
//             String msg = CHANNEL_NAME + " " + payCard.getBankName() + ChannelStringUtils.getMaskString(
//                     payCard.getNumber(), 0, 3, 4);
//             throw TryingBindCardException.builder()
//                     .msg(msg)
//                     .phoneNumber(payCard.getPhoneNumber())
//                     .tryPayPayloadJson(ChannelJSONUtil.toJson(payload))
//                     .build();
//        }
//        if (!this.checkIfBound(remitCard)) {
//            String bindCardUUID = this.bindCard(userId, remitCard, clientIP);
//            String msg = CHANNEL_NAME + " " + remitCard.getBankName() + ChannelStringUtils.getMaskString(
//                    remitCard.getNumber(), 0, 3, 4);
//            TryPayPayload payload = TryPayPayload.builder()
//                    .payCard(payCard)
//                    .remitCard(remitCard)
//                    .bindCardUUID(bindCardUUID)
//                    .orderAmount(orderAmount)
//                    .userFeeAmount(userFeeAmount)
//                    .userId(userId)
//                    .clientIP(clientIP)
//                    .payRate(payRate)
//                    .build();
//            throw TryingBindCardException.builder()
//                    .msg(msg)
//                    .phoneNumber(remitCard.getPhoneNumber())
//                    .tryPayPayloadJson(ChannelJSONUtil.toJson(payload))
//                    .build();
//        }
//        return this.pay(userId, payCard, remitCard, orderAmount, userFeeAmount, clientIP);
//    }

//    @Override
//    public String verifyPay(String userId, String smsCode, TryPayPayload payload) throws TryingBindCardException {
//        String uuid = payload.getBindCardUUID();
//        String cardId = this.bindCardConfirm(smsCode, userId, uuid); // 绑卡成功
//        // 接下来 重放消费
//        return this.tryPay(userId, payload.getPayCard(), payload.getRemitCard(),
//                payload.getOrderAmount(), payload.getUserFeeAmount(), payload.getClientIP(), payload.getPayRate());
//    }

//    @Override
//    public String remit(String userId, IBankCard card, BigDecimal amount, BigDecimal userFeeAmount) {
//        return null;
//    }

    @Override
    public String retryRemit(String flowId, Date date) {
        return null;
    }

    @Override
    public void handleCallback(String callBackAction, HttpServletRequest request, HttpServletResponse response, String orderCreateTimestamp, String info) {

    }
}
